#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include <error.h>
#include <errno.h>

#include "socket.h"

int init_ipv4_socket(char *ip_address, short port)
{
    int sfd4 = socket(AF_INET, SOCK_STREAM, 0);
    if (sfd4 == -1)
        error(-1, errno, "Unable to open AF_INET socket");

    struct sockaddr_in addr4;
    memset(&addr4, 0, sizeof(addr4));
    addr4.sin_family = AF_INET;
    addr4.sin_addr.s_addr = inet_addr(ip_address);
    addr4.sin_port = htons(port);

    if (bind(sfd4, (struct sockaddr *)&addr4, sizeof(struct sockaddr_in)) == -1)
        error(-1, errno, "Unable to bind ipv4 socket");

    if (listen(sfd4, DEFAULE_BACKLOG) == -1)
        error(-1, errno, "Unable to listen ipv4 socket");

    return sfd4;
}

int init_ipv6_socket(char *ip_address, short port)
{
    int sfd6 = socket(AF_INET6, SOCK_STREAM, 0);
    if (sfd6 == -1)
        error(-1, errno, "Unable to open AF_INET6 socket");

    struct sockaddr_in6 addr6;
    memset(&addr6, 0, sizeof(addr6));
    addr6.sin6_family = AF_INET6;
    inet_pton(AF_INET6, ip_address, &addr6.sin6_addr);
    addr6.sin6_port = htons(port);

    if (bind(sfd6, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) == -1)
        error(-1, errno, "Unable to bind ipv6 socket");

    if (listen(sfd6, DEFAULE_BACKLOG) == -1)
        error(-1, errno, "Unable to listen ipv6 socket");

    return sfd6;
}

int close_socket(int sfd)
{
    for (int i = 0; i < 5; i++)
    {
        if (shutdown(sfd, SHUT_RDWR) == -1)
        {
            fprintf(stderr, "Warning: Unable to shutdown socket fd: %d, try %d.\n", sfd, i);
        }
        else
            return 0;
    }
    return -1;
}